package org.truenewx.tnxjee.model.support;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.ConfigurableEnvironment;
import org.truenewx.tnxjee.core.util.ClassUtil;
import org.truenewx.tnxjee.model.CommandModel;
import org.truenewx.tnxjee.model.entity.unity.Unity;

public class CommandModelCheckListener implements SpringApplicationRunListener {

    private final SpringApplication application;

    public CommandModelCheckListener(SpringApplication application, String[] args) {
        this.application = application;
    }

    @Override
    public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,
            ConfigurableEnvironment environment) {
        Set<Object> sources = this.application.getAllSources();
        for (Object source : sources) {
            if (source instanceof Class<?> mainClass) {
                SpringBootApplication annotation = mainClass.getAnnotation(SpringBootApplication.class);
                if (annotation != null) {
                    Set<String> basePackages = new HashSet<>(Arrays.asList(annotation.scanBasePackages()));
                    for (Class<?> clazz : annotation.scanBasePackageClasses()) {
                        basePackages.add(clazz.getPackageName());
                    }
                    for (String basePackage : basePackages) {
                        ClassUtil.loopClass(basePackage, clazz -> {
                            if (CommandModel.class.isAssignableFrom(clazz) && clazz != CommandModel.class) {
                                Class<?> genericType = ClassUtil.getActualGenericType(clazz, CommandModel.class, 0);
                                // 只检查单体的命令模型
                                if (genericType != null && Unity.class.isAssignableFrom(genericType)) {
                                    try {
                                        Field field = clazz.getDeclaredField("id");
                                        System.out.println("The " + CommandModel.class.getSimpleName()
                                                + " cannot contain an '" + field.getName() + "' field, but "
                                                + clazz.getName() + " contains.");
                                        System.exit(1);
                                    } catch (NoSuchFieldException ignored) {
                                    }
                                }
                            }
                        });
                    }
                }
            }
        }
    }

}
